3//********************************************************
// **** ROUTINES FOR FAT32 IMPLEMATATION OF SD CARD *****
//********************************************************
//Controller: ATmega8 (Clock: 8 Mhz-internal)
//Compiler: AVR-GCC
//Version : 2.1
//Author: CC Dharmani, Chennai (India)
// www.dharmanitech.com
//Date: 26 Feb 2009 - updated 13 Sep 2009
//********************************************************
//Link to the Post: http://www.dharmanitech.com/2009/01/sd-card-interfacing-with-atmega8-fat32.html
//**************************************************
// ***** HEADER FILE : FAT32.h ******
//**************************************************
#ifndef _FAT32_H_
#define _FAT32_H_
//Structure to access Master Boot Record for getting info about partioions
struct MBRinfo_Structure{
unsigned char nothing[446]; //ignore, placed here to fill the gap in the structure
unsigned char partitionData[64]; //partition records (16x4)
unsigned int signature; //0xaa55
};
//Structure to access info of the first partioion of the disk
struct partitionInfo_Structure{
unsigned char
status;
//0x80 - active partition
unsigned char headStart; //starting head
unsigned int cylSectStart; //starting cylinder and sector
unsigned char
type;
//partition type
unsigned char headEnd; //ending head of the partition
unsigned int cylSectEnd; //ending cylinder and sector
unsigned long firstSector; //total sectors between MBR & the first sector of the partition
unsigned long sectorsTotal; //size of this partition in sectors
};
//Structure to access boot sector data
struct BS_Structure{
unsigned char jumpBoot[3]; //default: 0x009000EB
unsigned char OEMName[8];
unsigned int bytesPerSector; //deafault: 512
unsigned char sectorPerCluster;
unsigned int reservedSectorCount;
unsigned char numberofFATs;
unsigned int rootEntryCount;
unsigned int totalSectors_F16; //must be 0 for FAT32
unsigned char mediaType;
unsigned int FATsize_F16; //must be 0 for FAT32
unsigned int sectorsPerTrack;
unsigned int numberofHeads;
unsigned long hiddenSectors;
unsigned long totalSectors_F32;
unsigned long FATsize_F32; //count of sectors occupied by one FAT
unsigned int extFlags;
unsigned int FSversion; //0x0000 (defines version 0.0)
unsigned long rootCluster; //first cluster of root directory (=2)
unsigned int FSinfo; //sector number of FSinfo structure (=1)
unsigned int BackupBootSector;
unsigned char reserved[12];
unsigned char driveNumber;
unsigned char reserved1;
unsigned char bootSignature;
unsigned long volumeID;
unsigned char volumeLabel[11]; //"NO NAME "
unsigned char fileSystemType[8]; //"FAT32"
unsigned char bootData[420];
unsigned int bootEndSignature; //0xaa55
};
//Structure to access FSinfo sector data
struct FSInfo_Structure
{
unsigned long leadSignature; //0x41615252
unsigned char reserved1[480];
unsigned long structureSignature; //0x61417272
unsigned long freeClusterCount; //initial: 0xffffffff
unsigned long nextFreeCluster; //initial: 0xffffffff
unsigned char reserved2[12];
unsigned long trailSignature; //0xaa550000
};
//Structure to access Directory Entry in the FAT
struct dir_Structure{
unsigned char name[11];
unsigned char attrib; //file attributes
unsigned char NTreserved; //always 0
unsigned char timeTenth; //tenths of seconds, set to 0 here
unsigned int createTime; //time file was created
unsigned int createDate; //date file was created
unsigned int lastAccessDate;
unsigned int firstClusterHI; //higher word of the first cluster number
unsigned int writeTime; //time of last write
unsigned int writeDate; //date of last write
unsigned int firstClusterLO; //lower word of the first cluster number
unsigned long fileSize; //size of file in bytes
};
//Attribute definitions for file/directory
#define ATTR_READ_ONLY 0x01
#define ATTR_HIDDEN 0x02
#define ATTR_SYSTEM 0x04
#define ATTR_VOLUME_ID 0x08
#define ATTR_DIRECTORY 0x10
#define ATTR_ARCHIVE 0x20
#define ATTR_LONG_NAME 0x0f
#define DIR_ENTRY_SIZE 0x32
#define EMPTY 0x00
#define DELETED 0xe5
#define GET 0
#define SET 1
#define READ 0
#define VERIFY 1
#define ADD 0
#define REMOVE 1
#define TOTAL_FREE 1
#define NEXT_FREE 2
#define GET_LIST 0
#define GET_FILE 1
#define DELETE 2
#define EOF 0x0fffffff
//************* external variables *************
extern volatile unsigned char buffer[512];
extern volatile unsigned long startBlock;
extern volatile unsigned long firstDataSector, rootCluster, totalClusters;
extern volatile unsigned int bytesPerSector, sectorPerCluster, reservedSectorCount;
//global flag to keep track of free cluster count updating in FSinfo sector
unsigned char freeClusterCountUpdated;
unsigned long unusedSectors;
//************* functions *************
unsigned char getBootSectorData (void);
unsigned long getFirstSector(unsigned long clusterNumber);
unsigned long getSetFreeCluster(unsigned char totOrNext, unsigned char get_set, unsigned long FSEntry);
struct dir_Structure* findFiles (unsigned char flag, unsigned char *fileName);
unsigned long getSetNextCluster (unsigned long clusterNumber,unsigned char get_set,unsigned long clusterEntry);
unsigned char readFile (unsigned char flag, unsigned char *fileName);
unsigned char convertFileName (unsigned char *fileName);
void createFile (unsigned char *fileName);
unsigned long searchNextFreeCluster (unsigned long startCluster);
void memoryStatistics (void);
void displayMemory (unsigned long memory);
void deleteFile (unsigned char *fileName);
void freeMemoryUpdate (unsigned char flag, unsigned long size);
#endif
//*******************************************************
// **** ROUTINES FOR FAT32 IMPLEMATATION OF SD CARD ****
//*******************************************************
//Controller: ATmega8 (Clock: 8 Mhz-internal)
//Compiler: AVR-GCC
//Version : 2.0
//Author: CC Dharmani, Chennai (India)
// www.dharmanitech.com
//Date: 26 Feb 2009
//*******************************************************
//Link to the Post: http://www.dharmanitech.com/2009/01/sd-card-interfacing-with-atmega8-fat32.html
//**************************************************
// ***** SOURCE FILE : FAT32.c ******
//**************************************************
#include <avr/io.h>
#include <avr/pgmspace.h>
#include "FAT32.h"
#include "UART_routines.h"
#include "SD_routines.h"
//***************************************************************************
//Function: to read data from boot sector of SD card, to determine important
//parameters like bytesPerSector, sectorsPerCluster etc.
//Arguments: none
//return: none
//***************************************************************************
unsigned char getBootSectorData (void)
{
struct BS_Structure *bpb; //mapping the buffer onto the structure
struct MBRinfo_Structure *mbr;
struct partitionInfo_Structure *partition;
unsigned long dataSectors;
unusedSectors = 0;
SD_readSingleBlock(0);
bpb = (struct BS_Structure *)buffer;
if(bpb->jumpBoot[0]!=0xE9 && bpb->jumpBoot[0]!=0xEB) //check if it is boot sector
{
mbr = (struct MBRinfo_Structure *) buffer; //if it is not boot sector, it must be MBR
if(mbr->signature != 0xaa55) return 1; //if it is not even MBR then it's not FAT32
partition = (struct partitionInfo_Structure *)(mbr->partitionData);//first partition
unusedSectors = partition->firstSector; //the unused sectors, hidden to the FAT
SD_readSingleBlock(partition->firstSector);//read the bpb sector
bpb = (struct BS_Structure *)buffer;
if(bpb->jumpBoot[0]!=0xE9 && bpb->jumpBoot[0]!=0xEB) return 1;
}
bytesPerSector = bpb->bytesPerSector;
sectorPerCluster = bpb->sectorPerCluster;
reservedSectorCount = bpb->reservedSectorCount;
rootCluster = bpb->rootCluster;// + (sector / sectorPerCluster) +1;
firstDataSector = bpb->hiddenSectors + reservedSectorCount + (bpb->numberofFATs * bpb->FATsize_F32);
dataSectors = bpb->totalSectors_F32 -
bpb->reservedSectorCount - ( bpb->numberofFATs *
bpb->FATsize_F32);
totalClusters = dataSectors / sectorPerCluster;
if((getSetFreeCluster (TOTAL_FREE, GET, 0)) > totalClusters) //check if FSinfo free clusters count is valid
freeClusterCountUpdated = 0;
else
freeClusterCountUpdated = 1;
return 0;
}
//***************************************************************************
//Function: to calculate first sector address of any given cluster
//Arguments: cluster number for which first sector is to be found
//return: first sector address
//***************************************************************************
unsigned long getFirstSector(unsigned long clusterNumber)
{
return (((clusterNumber - 2) * sectorPerCluster) + firstDataSector);
}
//***************************************************************************
//Function: get cluster entry value from FAT to find out the next cluster in the chain
//or set new cluster entry in FAT
//Arguments: 1. current cluster number, 2. get_set (=GET, if next cluster is to be found or = SET,
//if next cluster is to be set 3. next cluster number, if argument#2 = SET, else 0
//return: next cluster number, if if argument#2 = GET, else 0
//****************************************************************************
unsigned long getSetNextCluster (unsigned long clusterNumber,
unsigned char get_set,
unsigned long clusterEntry)
{
unsigned int FATEntryOffset;
unsigned long *FATEntryValue;
unsigned long FATEntrySector;
unsigned char retry = 0;
//get sector number of the cluster entry in the FAT
FATEntrySector = unusedSectors + reservedSectorCount + ((clusterNumber * 4) / bytesPerSector) ;
//get the offset address in that sector number
FATEntryOffset = (unsigned int) ((clusterNumber * 4) % bytesPerSector);
//read the sector into a buffer
while(retry <10)
{ if(!SD_readSingleBlock(FATEntrySector)) break; retry++;}
//get the cluster address from the buffer
FATEntryValue = (unsigned long *) &buffer[FATEntryOffset];
if(get_set == GET)
return ((*FATEntryValue) & 0x0fffffff);
*FATEntryValue = clusterEntry; //for setting new value in cluster entry in FAT
SD_writeSingleBlock(FATEntrySector);
return (0);
}
//********************************************************************************************
//Function: to get or set next free cluster or total free clusters in FSinfo sector of SD card
//Arguments: 1.flag:TOTAL_FREE or NEXT_FREE,
// 2.flag: GET or SET
//
3.new FS entry, when argument2 is SET; or 0, when argument2 is GET
//return: -next free cluster, if arg1 is NEXT_FREE & arg2 is GET
// -total number of free clusters, if arg1 is TOTAL_FREE & arg2 is GET
// -0xffffffff, if any error or if arg2 is SET
//********************************************************************************************
unsigned long getSetFreeCluster(unsigned char totOrNext, unsigned char get_set, unsigned long FSEntry)
{
struct FSInfo_Structure *FS = (struct FSInfo_Structure *) &buffer;
unsigned char error;
SD_readSingleBlock(unusedSectors + 1);
if((FS->leadSignature != 0x41615252) || (FS->structureSignature != 0x61417272) || (FS->trailSignature !=0xaa550000))
return 0xffffffff;
if(get_set == GET)
{
if(totOrNext == TOTAL_FREE)
return(FS->freeClusterCount);
else // when totOrNext = NEXT_FREE
return(FS->nextFreeCluster);
}
else
{
if(totOrNext == TOTAL_FREE)
FS->freeClusterCount = FSEntry;
else // when totOrNext = NEXT_FREE
FS->nextFreeCluster = FSEntry;
error = SD_writeSingleBlock(unusedSectors + 1); //update FSinfo
}
return 0xffffffff;
}
//***************************************************************************
//Function: to get DIR/FILE list or a single file address (cluster number) or to delete a specified file
//Arguments: #1 - flag: GET_LIST, GET_FILE or DELETE #2 - pointer to file name (0 if arg#1 is GET_LIST)
//return: first cluster of the file, if flag = GET_FILE
// print file/dir list of the root directory, if flag = GET_LIST
// Delete the file mentioned in arg#2, if flag = DELETE
//****************************************************************************
struct dir_Structure* findFiles (unsigned char flag, unsigned char *fileName)
{
unsigned long cluster, sector, firstSector, firstCluster, nextCluster;
struct dir_Structure *dir;
unsigned int i;
unsigned char j;
cluster = rootCluster; //root cluster
while(1)
{
firstSector = getFirstSector (cluster);
for(sector = 0; sector < sectorPerCluster; sector++)
{
SD_readSingleBlock (firstSector + sector);
for(i=0; i<bytesPerSector; i+=32)
{
dir = (struct dir_Structure *) &buffer[i];
if(dir->name[0] == EMPTY) //indicates end of the file list of the directory
{
if((flag == GET_FILE) || (flag == DELETE))
transmitString_F(PSTR("File does not exist!"));
return 0;
}
if((dir->name[0] != DELETED) && (dir->attrib != ATTR_LONG_NAME))
{
if((flag == GET_FILE) || (flag == DELETE))
{
for(j=0; j<11; j++)
if(dir->name[j] != fileName[j]) break;
if(j == 11)
{
if(flag == GET_FILE)
return (dir);
else //when flag = DELETE
{
TX_NEWLINE;
transmitString_F(PSTR("Deleting.."));
TX_NEWLINE;
TX_NEWLINE;
firstCluster = (((unsigned long) dir->firstClusterHI) << 16) | dir->firstClusterLO;
//mark file as 'deleted' in FAT table
dir->name[0] = DELETED;
SD_writeSingleBlock (firstSector+sector);
freeMemoryUpdate (ADD, dir->fileSize);
//update next free cluster entry in FSinfo sector
cluster = getSetFreeCluster (NEXT_FREE, GET, 0);
if(firstCluster < cluster)
getSetFreeCluster (NEXT_FREE, SET,
firstCluster);
//mark all the clusters allocated to the file as 'free'
while(1)
{
nextCluster = getSetNextCluster (firstCluster, GET, 0);
getSetNextCluster (firstCluster, SET, 0);
if(nextCluster > 0x0ffffff6)
{transmitString_F(PSTR("File deleted!"));return 0;}
firstCluster = nextCluster;
}
}
}
}
else //when flag = GET_LIST
{
TX_NEWLINE;
for(j=0; j<11; j++)
{
if(j == 8) transmitByte(' ');
transmitByte (dir->name[j]);
}
transmitString_F (PSTR(" "));
if((dir->attrib != 0x10) && (dir->attrib != 0x08))
{
transmitString_F (PSTR("FILE" ));
transmitString_F (PSTR(" "));
displayMemory (dir->fileSize);
}
else
transmitString_F ((dir->attrib == 0x10)? PSTR("DIR") : PSTR("ROOT"));
}
}
}
}
cluster = (getSetNextCluster (cluster, GET, 0));
if(cluster > 0x0ffffff6)
return 0;
if(cluster == 0)
{transmitString_F(PSTR("Error in getting cluster")); return 0;}
}
return 0;
}
//***************************************************************************
//Function: if flag=READ then to read file from SD card and send contents to UART
//if flag=VERIFY then functions will verify whether a specified file is already existing
//Arguments: flag (READ or VERIFY) and pointer to the file name
//return: 0, if normal operation or flag is READ
// 1, if file is already existing and flag = VERIFY
// 2, if file name is incompatible
//***************************************************************************
unsigned char readFile (unsigned char flag, unsigned char *fileName)
{
struct dir_Structure *dir;
unsigned long cluster, byteCounter = 0, fileSize, firstSector;
unsigned int k;
unsigned char j, error;
error = convertFileName (fileName); //convert fileName into FAT format
if(error) return 2;
dir = findFiles (GET_FILE, fileName); //get the file location
if(dir == 0)
return (0);
if(flag == VERIFY) return (1); //specified file name is already existing
cluster = (((unsigned long) dir->firstClusterHI) << 16) | dir->firstClusterLO;
fileSize = dir->fileSize;
TX_NEWLINE;
TX_NEWLINE;
while(1)
{
firstSector = getFirstSector (cluster);
for(j=0; j<8; j++)
{
SD_readSingleBlock(firstSector + j);
for(k=0; k<512; k++)
{
transmitByte(buffer[k]);
if ((byteCounter++) >= fileSize ) return 0;
}
}
cluster = getSetNextCluster (cluster, GET, 0);
if(cluster == 0) {transmitString_F(PSTR("Error in getting cluster")); return 0;}
}
return 0;
}
//***************************************************************************
//Function: to convert normal short file name into FAT format
//Arguments: pointer to the file name
//return: 0-if no error, 1-if error
//****************************************************************************
unsigned char convertFileName (unsigned char *fileName)
{
unsigned char fileNameFAT[11];
unsigned char j, k;
for(j=0; j<12; j++)
if(fileName[j] == '.') break;
if(j>8) {transmitString_F(PSTR("Invalid fileName..")); return 1;}
for(k=0; k<j; k++) //setting file name
fileNameFAT[k] = fileName[k];
for(k=j; k<=7; k++) //filling file name trail with blanks
fileNameFAT[k] = ' ';
j++;
for(k=8; k<11; k++) //setting file extention
{
if(fileName[j] != 0)
fileNameFAT[k] = fileName[j++];
else //filling extension trail with blanks
while(k<11)
fileNameFAT[k++] = ' ';
}
for(j=0; j<11; j++) //converting small letters to caps
if((fileNameFAT[j] >= 0x61) && (fileNameFAT[j] <= 0x7a))
fileNameFAT[j] -= 0x20;
for(j=0; j<11; j++)
fileName[j] = fileNameFAT[j];
return 0;
}
//***************************************************************************
//Function: to create a file in FAT32 format in the root directory
//Arguments: pointer to the file name
//return: none
//***************************************************************************
void createFile (unsigned char *fileName)
{
unsigned char j, data, error, fileCreatedFlag = 0;
unsigned int i, firstClusterHigh, firstClusterLow;
struct dir_Structure *dir;
unsigned long cluster, prevCluster, firstSector, sector;
unsigned long size;
j = readFile (VERIFY, fileName);
if(j == 1) {transmitString_F(PSTR(" File already existing")); return;}
if(j == 2) return; //invalid file name
TX_NEWLINE;
transmitString_F(PSTR(" Creating File.."));
cluster = getSetFreeCluster (NEXT_FREE, GET, 0);
if(cluster > totalClusters)
cluster = rootCluster;
cluster = searchNextFreeCluster(cluster);
if(cluster == 0)
{
TX_NEWLINE;
transmitString_F(PSTR(" No free cluster!"));
return;
}
//transmitHex(LONG, cluster);
firstClusterHigh = (unsigned int) ((cluster & 0xffff0000) >> 16 );
firstClusterLow = (unsigned int) ( cluster & 0x0000ffff);
size = 0;
while(1)
{
getSetNextCluster (cluster, SET, EOF); //last cluster of the file, marked EOF
startBlock = getFirstSector (cluster);
TX_NEWLINE;
transmitString_F(PSTR(" Enter text (end with ~):"));
i=0;
j=0;
do
{
data = receiveByte();
if(data == 0x08) //'Back Space' key pressed
{
if(i != 0)
{
transmitByte(data);
transmitByte(' ');
transmitByte(data);
i--;
size--;
}
continue;
}
transmitByte(data);
buffer[i++] = data;
size++;
if(data == '\r') //'Carriege Return (CR)' character
{
transmitByte('\n');
buffer[i++] = '\n'; //appending 'Line Feed (LF)' character
size++;
}
if(i == 512)
{
i=0;
error = SD_writeSingleBlock (startBlock);
j++;
if(j == sectorPerCluster) {j = 0; break;}
startBlock++;
}
}while (data != '~');
if(data == '~')
{
size--; //to remove the last entered '~' character
i--;
for(;i<512;i++) //fill the rest of the buffer with 0x00
buffer[i]= 0x00;
error = SD_writeSingleBlock (startBlock);
break;
}
prevCluster = cluster;
cluster = searchNextFreeCluster(prevCluster); //look for a free cluster starting from the current cluster
if(cluster == 0)
{
TX_NEWLINE;
transmitString_F(PSTR(" No free cluster!"));
return;
}
getSetNextCluster(prevCluster, SET, cluster);
}
getSetFreeCluster (NEXT_FREE, SET, cluster); //update FSinfo next free cluster entry
prevCluster = rootCluster; //root cluster
while(1)
{
firstSector = getFirstSector (prevCluster);
for(sector = 0; sector < sectorPerCluster; sector++)
{
SD_readSingleBlock (firstSector + sector);
for(i=0; i<bytesPerSector; i+=32)
{
dir = (struct dir_Structure *) &buffer[i];
if(fileCreatedFlag) //to mark last directory entry with 0x00 (empty) mark
{
//indicating end of the directory file list
dir->name[0] = 0x00;
return;
}
if((dir->name[0] == EMPTY) || (dir->name[0] == DELETED)) //looking for an empty slot to enter file info
{
for(j=0; j<11; j++)
dir->name[j] = fileName[j];
dir->attrib =
ATTR_ARCHIVE; //settting file attribute as 'archive'
dir->NTreserved = 0;
//always set to 0
dir->timeTenth = 0;
//always set to 0
dir->createTime =
0x9684; //fixed time of creation
dir->createDate =
0x3a37; //fixed date of creation
dir->lastAccessDate = 0x3a37; //fixed date of last access
dir->writeTime = 0x9684;
//fixed time of last write
dir->writeDate = 0x3a37;
//fixed date of last write
dir->firstClusterHI = firstClusterHigh;
dir->firstClusterLO = firstClusterLow;
dir->fileSize = size;
SD_writeSingleBlock (firstSector + sector);
fileCreatedFlag = 1;
TX_NEWLINE;
TX_NEWLINE;
transmitString_F(PSTR(" File Created!"));
freeMemoryUpdate (REMOVE, size); //updating free memory count in FSinfo sector
}
}
}
cluster = getSetNextCluster (prevCluster, GET, 0);
if(cluster > 0x0ffffff6)
{
if(cluster == EOF) //this situation will come when total files in root is multiple of (32*sectorPerCluster)
{
cluster = searchNextFreeCluster(prevCluster);
//find next cluster for root directory entries
getSetNextCluster(prevCluster, SET, cluster);
//link the new cluster of root to the previous cluster
getSetNextCluster(cluster, SET, EOF);
//set the new cluster as end of the root directory
}
else
{
transmitString_F(PSTR("End of Cluster Chain"));
return;
}
}
if(cluster == 0) {transmitString_F(PSTR("Error in getting cluster")); return;}
prevCluster = cluster;
}
return;
}
//***************************************************************************
//Function: to search for the next free cluster in the root directory
// starting from a specified cluster
//Arguments: Starting cluster
//return: the next free cluster
//****************************************************************
unsigned long searchNextFreeCluster (unsigned long startCluster)
{
unsigned long cluster, *value, sector;
unsigned char i;
startCluster -= (startCluster % 128); //to start with the first file in a FAT sector
for(cluster =startCluster; cluster <totalClusters; cluster+=128)
{
sector = unusedSectors + reservedSectorCount + ((cluster * 4) / bytesPerSector);
SD_readSingleBlock(sector);
for(i=0; i<128; i++)
{
value = (unsigned long *) &buffer[i*4];
if(((*value) & 0x0fffffff) == 0)
return(cluster+i);
}
}
return 0;
}
//***************************************************************************
//Function: to display total memory and free memory of SD card, using UART
//Arguments: none
//return: none
//Note: this routine may take upto 15sec for 1GB card (@8MHz clock)
//it tries to read from SD whether a free cluster count is stored, if it is stored
//then it will return immediately. Otherwise it will count the total number of
//free clusters, which takes time
//****************************************************************************
void memoryStatistics (void)
{
unsigned long totalMemory, freeMemory, freeClusters, totalClusterCount, cluster;
unsigned long sector, *value;
unsigned int i;
totalMemory = totalClusters * sectorPerCluster * bytesPerSector;
TX_NEWLINE;
TX_NEWLINE;
transmitString_F(PSTR("Total Memory: "));
displayMemory (totalMemory);
freeClusters = getSetFreeCluster (TOTAL_FREE, GET, 0);
//freeClusters = 0xffffffff;
if(freeClusters > totalClusters)
{
freeClusterCountUpdated = 0;
freeClusters = 0;
totalClusterCount = 0;
cluster = rootCluster;
while(1)
{
sector = unusedSectors + reservedSectorCount + ((cluster * 4) / bytesPerSector) ;
SD_readSingleBlock(sector);
for(i=0; i<128; i++)
{
value = (unsigned long *) &buffer[i*4];
if(((*value)& 0x0fffffff) == 0)
freeClusters++;;
totalClusterCount++;
if(totalClusterCount == (totalClusters+2)) break;
}
if(i < 128) break;
cluster+=128;
}
}
if(!freeClusterCountUpdated)
getSetFreeCluster (TOTAL_FREE, SET, freeClusters); //update FSinfo total free cluster entry
freeClusterCountUpdated = 1; //set flag
freeMemory = freeClusters * sectorPerCluster * bytesPerSector;
TX_NEWLINE;
transmitString_F(PSTR(" Free Memory: "));
displayMemory (freeMemory);
TX_NEWLINE;
}
//************************************************************
//Function: To convert the unsigned long value of memory into
// text string and send to UART
//Arguments: unsigned long memory value
//return: none
//************************************************************
void displayMemory (unsigned long memory)
{
unsigned char memoryString[] = " Bytes"; //18 character long string for memory display
unsigned char i;
for(i=12; i>0; i--) //converting freeMemory into ASCII string
{
if(i == 5 || i == 9)
{
memoryString[i-1] = ',';
i--;
}
memoryString[i-1] = (memory % 10) | 0x30;
memory /= 10;
if(memory == 0) break;
}
transmitString(memoryString);
}
//********************************************************************
//Function: to delete a specified file from the root directory
//Arguments: pointer to the file name
//return: none
//********************************************************************
void deleteFile (unsigned char *fileName)
{
unsigned char error;
error = convertFileName (fileName);
if(error) return;
findFiles (DELETE, fileName);
}
//********************************************************************
//Function: update the free memory count in the FSinfo sector.
// Whenever a file is deleted or created, this function will be called
// to ADD or REMOVE clusters occupied by the file
//Arguments: #1.flag ADD or REMOVE #2.file size in Bytes
//return: none
//********************************************************************
void freeMemoryUpdate (unsigned char flag, unsigned long size)
{
unsigned long freeClusters;
//convert file size into number of clusters occupied
if((size % 512) == 0) size = size / 512;
else size = (size / 512) +1;
if((size % 8) == 0) size = size / 8;
else size = (size / 8) +1;
if(freeClusterCountUpdated)
{
freeClusters = getSetFreeCluster (TOTAL_FREE, GET, 0);
if(flag == ADD)
freeClusters = freeClusters + size;
else //when flag = REMOVE
freeClusters = freeClusters - size;
getSetFreeCluster (TOTAL_FREE, SET, freeClusters);
}
}
//******** END ****** www.dharmanitech.com *****